﻿using Exceptionless;
using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Helpers;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Builder;
using Serilog.AspNetCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.ServiceProcess;
using System.Linq;

public static class SerilogHelperExtensions
{
    /// <summary>
    /// 初始化serilog,并注册Serilog.ILogger
    /// </summary>
    public static IServiceCollection AddSerilogHelper(this IServiceCollection services, IConfiguration configuration, Action<SerilogHelperOptions> configureOptions = default, Action<LoggerConfiguration, SerilogHelperOptions> configureLogger = default)
    {
        SerilogFactory.Init(configuration, configureOptions, configureLogger, services);

        //注册ILogger
        services.AddSingleton<ILogger>(x => Log.Logger);

        return services;
    }

    /// <summary>
    /// 使用serilog记录请求中间件
    /// </summary>
    public static IApplicationBuilder UseSerilogRequestLoggingz(this IApplicationBuilder app, Action<RequestLoggingOptions> configureOptions = null)
    {
        app.UseSerilogRequestLogging(options =>
        {
            options.MessageTemplate = "Request {RequestProtocol} {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.00}ms";
            options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
            {
                diagnosticContext.Set("RequestId", httpContext.TraceIdentifier);
                diagnosticContext.Set("RequestProtocol", httpContext.Request.Protocol);
            };
            configureOptions?.Invoke(options);
        });
        return app;
    }

    #region 获取服务进程id
    //internal sealed class SERVICE_STATUS_PROCESS
    //{
    //    [MarshalAs(UnmanagedType.U4)]
    //    public uint dwServiceType;
    //    [MarshalAs(UnmanagedType.U4)]
    //    public uint dwCurrentState;
    //    [MarshalAs(UnmanagedType.U4)]
    //    public uint dwControlsAccepted;
    //    [MarshalAs(UnmanagedType.U4)]
    //    public uint dwWin32ExitCode;
    //    [MarshalAs(UnmanagedType.U4)]
    //    public uint dwServiceSpecificExitCode;
    //    [MarshalAs(UnmanagedType.U4)]
    //    public uint dwCheckPoint;
    //    [MarshalAs(UnmanagedType.U4)]
    //    public uint dwWaitHint;
    //    [MarshalAs(UnmanagedType.U4)]
    //    public uint dwProcessId;
    //    [MarshalAs(UnmanagedType.U4)]
    //    public uint dwServiceFlags;
    //}

    //internal const int ERROR_INSUFFICIENT_BUFFER = 0x7a;
    //internal const int SC_STATUS_PROCESS_INFO = 0;

    //[DllImport("advapi32.dll", SetLastError = true)]
    //internal static extern bool QueryServiceStatusEx(SafeHandle hService, int infoLevel, IntPtr lpBuffer, uint cbBufSize, out uint pcbBytesNeeded);

    ///// <summary>
    ///// 获取服务进程id
    ///// </summary>
    ///// <param name="sc"></param>
    ///// <returns></returns>
    //public static int GetServiceProcessId(this ServiceController sc)
    //{
    //    if (sc == null)
    //        throw new ArgumentNullException("sc");

    //    IntPtr zero = IntPtr.Zero;

    //    try
    //    {
    //        UInt32 dwBytesNeeded;
    //        // Call once to figure the size of the output buffer.
    //        QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, 0, out dwBytesNeeded);
    //        if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
    //        {
    //            // Allocate required buffer and call again.
    //            zero = Marshal.AllocHGlobal((int)dwBytesNeeded);

    //            if (QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, dwBytesNeeded, out dwBytesNeeded))
    //            {
    //                var ssp = new SERVICE_STATUS_PROCESS();
    //                Marshal.PtrToStructure(zero, ssp);
    //                return (int)ssp.dwProcessId;
    //            }
    //        }
    //    }
    //    finally
    //    {
    //        if (zero != IntPtr.Zero)
    //        {
    //            Marshal.FreeHGlobal(zero);
    //        }
    //    }
    //    return -1;
    //}

    //public static string GetServiceNameByCurrentProcess()
    //{
    //    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    //    {
    //        var pid = Process.GetCurrentProcess().Id;
    //        ServiceController[] serviceController = ServiceController.GetServices();
    //        var service = serviceController.Where(x => x.Status == ServiceControllerStatus.Running && x.GetServiceProcessId() == pid).FirstOrDefault();
    //        if (service != null)
    //        {
    //            return service.ServiceName;
    //        }
    //    }
    //    return string.Empty;
    //}

    #endregion
}
